#ifndef TRIENODE_H
#define	TRIENODE_H

#include <string>
#include <iostream>

template <class T>
class TrieNode
{
public:

    TrieNode(char key)
    {
        this->next_ = 0;
        this->children_ = 0;
        this->key_ = key;
        this->value_ = 0;
        this->isWord_ = false;
    }
    
    const char getKey() const
    {
        return this->key_;
    }
    
    TrieNode<T>* getNext()
    {
        return this->next_;
    }
    
    T* getValue()
    {
        return this->value_;
    }
    
    bool isWord() const
    {
        return this->isWord_;
    }
    
    TrieNode<T>* getChildren()
    {
        return this->children_;
    }

    void addWord(std::string word, size_t pos, T& value)
    {
        if (word.at(pos) == this->key_)
        {
            if (!this->children_)
            {
                if (pos == word.size() - 1)
                {
                    if (this->isWord_ == false)
                    {
                        this->value_ = &value;
                        this->isWord_ = true;
                    }
                }
                else
                {
                    this->children_ = new TrieNode<T>(word.at(pos + 1));
                    this->children_->addWord(word, pos + 1, value);
                }
            }
            else
                this->children_->addWord(word, pos + 1, value);
        }
        else
        {
            if (!this->next_)
                this->next_ = new TrieNode<T>(word.at(pos));
            this->next_->addWord(word, pos, value);
        }
    }

    T* search(std::string word, size_t pos)
    {
        T* found = 0;
        if (word.at(pos) == this->key_)
        {
            if (this->children_)
            {
                if (pos < word.size() - 1)
                    found = this->children_->search(word, pos + 1);
            }
            else
            {
                if (pos == word.size() - 1 && this->isWord_)
                    found = this->value_;
            }
        }
        else
        {
            if (this->next_)
                found = this->next_->search(word, pos);
        }
        return found;
    }

private:
    TrieNode<T>* next_;
    TrieNode<T>* children_;
    char key_;
    T* value_;
    bool isWord_;
};

#endif	/* TRIENODE_H */

